home *** CD-ROM | disk | FTP | other *** search
- // VirtualDub - Video processing and capture application
- // Copyright (C) 1998-2001 Avery Lee
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- #include "VirtualDub.h"
- #include <crtdbg.h>
- #include <stdio.h>
-
- #include <windows.h>
-
- #include "ScriptValue.h"
- #include "ScriptInterpreter.h"
- #include "ScriptError.h"
-
- #include "resource.h"
- #include "filter.h"
- #include "dub.h"
-
- #include "disasm.h"
-
- #include "f_convolute.h"
-
- #define USE_ASM
- #define USE_ASM_DYNAMIC
-
- extern "C" void asm_convolute_run(
- void *dst,
- void *src,
- unsigned long width,
- unsigned long height,
- unsigned long srcstride,
- unsigned long dststride,
- const long *matrix);
-
- extern "C" void asm_dynamic_convolute_run(
- void *dst,
- void *src,
- unsigned long width,
- unsigned long height,
- unsigned long srcstride,
- unsigned long dststride,
- const long *matrix,
- const void *dyna_func);
-
- extern HINSTANCE g_hInst;
-
- ///////////////////////////////////
-
- #define C_TOPOK (1)
- #define C_BOTTOMOK (2)
- #define C_LEFTOK (4)
- #define C_RIGHTOK (8)
-
- static void inline conv_add(long& rt, long& gt, long& bt, unsigned long dv, long m) {
- bt += m*(0xFFUL & (dv));
- gt += m*(0xFFUL & (dv>>8));
- rt += m*(0xFFUL & (dv>>16));
- }
-
- /* conv_clip_tab: number of times center should be added */
-
- static unsigned long __fastcall do_conv(unsigned long *data, const ConvoluteFilterData *cfd, long sflags, long pit) {
- long rt0=cfd->m[9], gt0=cfd->m[9], bt0=cfd->m[9];
- long rt,gt,bt;
-
- if (sflags & C_TOPOK) {
- if (sflags & (C_LEFTOK)) conv_add(rt0, gt0, bt0, data[ -1], cfd->m[6]);
- else conv_add(rt0, gt0, bt0, data[ 0], cfd->m[6]);
-
- conv_add(rt0, gt0, bt0, data[ 0], cfd->m[7]);
-
- if (sflags & (C_RIGHTOK)) conv_add(rt0, gt0, bt0, data[ +1], cfd->m[8]);
- else conv_add(rt0, gt0, bt0, data[ 0], cfd->m[8]);
- } else {
- // top is clipped... push down.
-
- if (sflags & (C_LEFTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)-1], cfd->m[6]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[6]);
-
- conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[7]);
-
- if (sflags & (C_RIGHTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)+1], cfd->m[8]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[8]);
-
- }
-
- if (sflags & (C_LEFTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)-1], cfd->m[3]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[3]);
-
- conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[4]);
-
- if (sflags & (C_RIGHTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)+1], cfd->m[5]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[5]);
-
- if (sflags & C_BOTTOMOK) {
- if (sflags & (C_LEFTOK)) conv_add(rt0, gt0, bt0, data[(pit>>1)-1], cfd->m[0]);
- else conv_add(rt0, gt0, bt0, data[(pit>>1) ], cfd->m[0]);
-
- conv_add(rt0, gt0, bt0, data[(pit>>1) ], cfd->m[1]);
-
- if (sflags & (C_RIGHTOK)) conv_add(rt0, gt0, bt0, data[(pit>>1)+1], cfd->m[2]);
- else conv_add(rt0, gt0, bt0, data[(pit>>1) ], cfd->m[2]);
- } else {
- // bottom is clipped... push up.
-
- if (sflags & (C_LEFTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)-1], cfd->m[0]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[0]);
-
- conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[1]);
-
- if (sflags & (C_RIGHTOK)) conv_add(rt0, gt0, bt0, data[(pit>>2)+1], cfd->m[2]);
- else conv_add(rt0, gt0, bt0, data[(pit>>2) ], cfd->m[2]);
- }
-
- rt = rt0>>8; if (rt<0) rt=0; else if (rt>255) rt=255;
- gt = gt0>>8; if (gt<0) gt=0; else if (gt>255) gt=255;
- bt = bt0>>8; if (bt<0) bt=0; else if (bt>255) bt=255;
-
- return (unsigned long)((rt<<16) | (gt<<8) | (bt));
- }
-
- static inline unsigned long do_conv2(unsigned long *data, const long *m, long pit) {
- long rt0=m[9], gt0=m[9], bt0=m[9];
- long rt,gt,bt;
-
- conv_add(rt0, gt0, bt0, data[ -1], m[6]);
- conv_add(rt0, gt0, bt0, data[ 0], m[7]);
- conv_add(rt0, gt0, bt0, data[ +1], m[8]);
- conv_add(rt0, gt0, bt0, data[(pit>>2)-1], m[3]);
- conv_add(rt0, gt0, bt0, data[(pit>>2) ], m[4]);
- conv_add(rt0, gt0, bt0, data[(pit>>2)+1], m[5]);
- conv_add(rt0, gt0, bt0, data[(pit>>1)-1], m[0]);
- conv_add(rt0, gt0, bt0, data[(pit>>1) ], m[1]);
- conv_add(rt0, gt0, bt0, data[(pit>>1)+1], m[2]);
-
- rt = rt0>>8; if (rt<0) rt=0; else if (rt>255) rt=255;
- gt = gt0>>8; if (gt<0) gt=0; else if (gt>255) gt=255;
- bt = bt0>>8; if (bt<0) bt=0; else if (bt>255) bt=255;
-
- return (unsigned long)((rt<<16) | (gt<<8) | (bt));
- }
-
- int filter_convolute_run(const FilterActivation *fa, const FilterFunctions *ff) {
- unsigned long w,h;
- unsigned long *src = (unsigned long *)fa->src.data, *dst = (unsigned long *)fa->dst.data;
- unsigned long pitch = fa->src.pitch;
- const ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
- const long *const m = cfd->m;
-
- #ifdef USE_ASM
- #ifdef USE_ASM_DYNAMIC
- if (((ConvoluteFilterData *)fa->filter_data)->dyna_func)
- asm_dynamic_convolute_run(dst+(fa->dst.pitch>>2)+1, src, fa->src.w-2, fa->src.h-2, fa->dst.pitch, fa->src.pitch, m, ((ConvoluteFilterData *)fa->filter_data)->dyna_func);
- else
- #endif
- asm_convolute_run(dst+(fa->dst.pitch>>2)+1, src, fa->src.w-2, fa->src.h-2, fa->dst.pitch, fa->src.pitch, m);
- #endif
-
- src -= pitch>>2;
-
- *dst++ = do_conv(src++, cfd, C_BOTTOMOK | C_RIGHTOK, pitch);
- w = fa->src.w-2;
- do { *dst++ = do_conv(src++, cfd, C_BOTTOMOK | C_LEFTOK | C_RIGHTOK, pitch); } while(--w);
- *dst++ = do_conv(src++, cfd, C_BOTTOMOK | C_LEFTOK, pitch);
-
- src += fa->src.modulo>>2;
- dst += fa->dst.modulo>>2;
-
- #ifndef USE_ASM
- h = fa->src.h-2;
- do {
- *dst++ = do_conv(src++, cfd, C_TOPOK | C_BOTTOMOK | C_RIGHTOK, pitch);
- w = fa->src.w-2;
- do { *dst++ = do_conv2(src++, m, pitch); } while(--w);
- *dst++ = do_conv(src++, cfd, C_TOPOK | C_BOTTOMOK | C_LEFTOK, pitch);
-
- src += fa->src.modulo>>2;
- dst += fa->dst.modulo>>2;
- } while(--h);
- #else
- h = fa->src.h-2;
- w = fa->src.w;
- do {
- dst[0] = do_conv(src+0, cfd, C_TOPOK | C_BOTTOMOK | C_RIGHTOK, pitch);
- dst[w-1] = do_conv(src+w-1, cfd, C_TOPOK | C_BOTTOMOK | C_LEFTOK, pitch);
-
- src += fa->src.pitch>>2;
- dst += fa->dst.pitch>>2;
- } while(--h);
- #endif
-
- *dst++ = do_conv(src++, cfd, C_TOPOK | C_RIGHTOK, pitch);
- w = fa->src.w-2;
- do { *dst++ = do_conv(src++, cfd, C_TOPOK | C_LEFTOK | C_RIGHTOK, pitch); } while(--w);
- *dst++ = do_conv(src++, cfd, C_TOPOK | C_LEFTOK, pitch);
-
- return 0;
- }
-
- long filter_convolute_param(FilterActivation *fa, const FilterFunctions *ff) {
- return FILTERPARAM_SWAP_BUFFERS;
- }
-
- //////////////////
-
- static int convolute_init(FilterActivation *fa, const FilterFunctions *ff) {
- ((ConvoluteFilterData *)fa->filter_data)->m[4] = 256;
- ((ConvoluteFilterData *)fa->filter_data)->bias = 128;
- ((ConvoluteFilterData *)fa->filter_data)->dyna_func = NULL;
-
- return 0;
- }
-
- static BOOL APIENTRY convoluteDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
- int i;
-
- switch (message)
- {
- case WM_INITDIALOG:
- {
- struct ConvoluteFilterData *cfd = (ConvoluteFilterData *)lParam;
-
- CheckDlgButton(hDlg, IDC_ENABLE_CLIPPING, cfd->fClip);
- SetDlgItemInt(hDlg, IDC_BIAS, (cfd->bias-128)>>8, TRUE);
-
- for(i=0; i<9; i++)
- SetDlgItemInt(hDlg, IDC_MATRIX_1+i, cfd->m[i], TRUE);
-
- SetWindowLong(hDlg, DWL_USER, (LONG)cfd);
- }
- return (TRUE);
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK) {
- struct ConvoluteFilterData *cfd = (struct ConvoluteFilterData *)GetWindowLong(hDlg, DWL_USER);
-
- cfd->fClip = IsDlgButtonChecked(hDlg, IDC_ENABLE_CLIPPING);
- cfd->bias = GetDlgItemInt(hDlg, IDC_BIAS, NULL, TRUE)*256 + 128;
-
- for(i=0; i<9; i++)
- cfd->m[i] = GetDlgItemInt(hDlg, IDC_MATRIX_1+i, NULL, TRUE);
-
- EndDialog(hDlg, 0);
- return TRUE;
- } else if (LOWORD(wParam) == IDCANCEL) {
- EndDialog(hDlg, 1);
- return TRUE;
- }
- break;
- }
- return FALSE;
- }
-
- static int convolute_config(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd) {
- return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER_CONVOLUTE), hWnd, convoluteDlgProc, (LONG)fa->filter_data);
- }
-
- static void convolute_script_config(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
- FilterActivation *fa = (FilterActivation *)lpVoid;
- int lv = argv[0].asInt();
-
- ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
-
- for(int i=0; i<9; i++) {
- cfd->m[i] = argv[i].asInt();
- }
-
- cfd->bias = argv[9].asInt();
- cfd->fClip = !!argv[10].asInt();
- }
-
- static ScriptFunctionDef convolute_func_defs[]={
- { (ScriptFunctionPtr)convolute_script_config, "Config", "0iiiiiiiiiii" },
- { NULL },
- };
-
- static CScriptObject convolute_obj={
- NULL, convolute_func_defs
- };
-
- static bool convolute_script_line(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen) {
- ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
-
- _snprintf(buf, buflen, "Config(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)"
- ,cfd->m[0]
- ,cfd->m[1]
- ,cfd->m[2]
- ,cfd->m[3]
- ,cfd->m[4]
- ,cfd->m[5]
- ,cfd->m[6]
- ,cfd->m[7]
- ,cfd->m[8]
- ,cfd->bias
- ,cfd->fClip?1:0
- );
-
- return true;
- }
-
- ///////////////////////////////////
-
- extern DubOptions g_dubOpts;
-
- #define REG_EAX (0)
- #define REG_ECX (1)
- #define REG_EDX (2)
- #define REG_EBX (3)
- #define REG_ESP (4)
- #define REG_EBP (5)
- #define REG_ESI (6)
- #define REG_EDI (7)
-
- char *DCG_emit_MOV(char *ptr, int dest, int src) {
- ptr[0] = (char)0x8b;
- ptr[1] = 0xc0 + (dest<<3) + src;
-
- return ptr+2;
- }
-
- char *DCG_emit_MOV_from_indexed(char *ptr, int dest, int src, long disp32) {
- ptr[0] = (char)0x8b;
- if (src != REG_ESP) {
- if (src != REG_EBP && !disp32) {
- ptr[1] = (dest<<3) + src;
- return ptr+2;
- }
- if (disp32>=-128 && disp32<128) {
- ptr[1] = 0x40 + (dest<<3) + src;
- ptr[2] = disp32 & 0xff;
- return ptr+3;
- }
- ptr[1] = 0x80 + (dest<<3) + src;
- *(long *)(ptr+2) = disp32;
- return ptr+6;
- }
-
- ptr[2] = 0x24;
- if (!disp32) {
- ptr[1] = 0x00 + (dest<<3);
- return ptr+3;
- }
- if (disp32>=-128 && disp32<128) {
- ptr[1] = 0x40 + (dest<<3);
- ptr[3] = 0;
- return ptr+4;
- }
- ptr[1] = 0x80 + (dest<<3);
- *(long *)(ptr+3) = 0;
- return ptr+7;
- }
-
- char *DCG_emit_ADD(char *ptr, int dest, int src) {
- ptr[0] = 0x03;
- ptr[1] = 0xc0 + (dest<<3) + src;
-
- return ptr+2;
- }
-
- char *DCG_emit_SUB(char *ptr, int dest, int src) {
- ptr[0] = 0x2B;
- ptr[1] = 0xc0 + (dest<<3) + src;
-
- return ptr+2;
- }
-
- char *DCG_emit_SHL(char *ptr, int dest, int bits) {
- if (bits==1) {
- ptr[0] = (char)0xd1;
- ptr[1] = 0xe0 + dest;
-
- return ptr+2;
- }
- ptr[0] = (char)0xc1;
- ptr[1] = 0xe0 + dest;
- ptr[2] = bits;
-
- return ptr+3;
- }
-
- char *DCG_emit_SHR(char *ptr, int dest, int bits) {
- if (bits==1) {
- ptr[0] = (char)0xd1;
- ptr[1] = 0xe8 + dest;
-
- return ptr+2;
- }
- ptr[0] = (char)0xc1;
- ptr[1] = 0xe8 + dest;
- ptr[2] = bits;
-
- return ptr+3;
- }
-
- char *DCG_emit_AND_immediate(char *ptr, int dest, long imm32) {
- ptr[0] = (char)0x81;
- ptr[1] = 0xe0 + dest;
- *(long *)(ptr+2) = imm32;
-
- return ptr+6;
- }
-
- // LEA dest,[src1*scale] (scale = 0 to 3)
-
- char *DCG_emit_LEA(char *ptr, int dest, int src1, int scale) {
- ptr[0] = (char)0x8d;
- if (!scale && src1!=REG_EBP && src1!=REG_ESP) {
- ptr[1] = (dest<<3) | src1;
- return ptr+2;
- }
- ptr[1] = 0x04 | (dest<<3);
- ptr[2] = (scale<<6) | (src1<<3) | 0x05;
- *(long *)(ptr+3)=0;
-
- return ptr+7;
- }
-
- // LEA dest,[src2 + src1*scale]
-
- char *DCG_emit_LEA(char *ptr, int dest, int src1, int scale, int src2) {
- ptr[0] = (char)0x8d;
- if (src2 == REG_EBP) {
- ptr[1] = 0x44 | (dest<<3);
- ptr[2] = (scale<<6) | (src1<<3) | src2;
- ptr[3] = 0;
- return ptr+4;
- }
- ptr[1] = 0x04 | (dest<<3);
- ptr[2] = (scale<<6) | (src1<<3) | src2;
-
- return ptr+3;
- }
-
- enum {
- CODE_LEA1 = 0, // 2 dest * 2 src1 * 2 src2 * 4 multipliers = 32 ops
- CODE_LEA2 = 32, // 2 dest * 2 src1 * 4 multipliers = 16 ops
- CODE_SHL = 48, // 2 dest * 16 shifts = 32 ops
- CODE_SUB = 80, // 2 dest * 2 src = 4 ops
- CODE_MAX = 84
- };
-
- // src2(16), multiplier(4), src1(2), dest(1)
-
- char *DCG_emit_mult_op(char *ptr, int reg1, int reg2, char op) {
- if (op < CODE_LEA2) {
- // special cases:
- // add - scale=1, src1=dest or src2=dest
-
- if (!(op&12) && !((op ^ (op>>1))&1))
- return DCG_emit_ADD(ptr, op&1 ? reg2 : reg1, op&16 ? reg2 : reg1);
- else if (!(op&12) && !((op ^ (op>>4))&1))
- return DCG_emit_ADD(ptr, op&1 ? reg2 : reg1, op&2 ? reg2 : reg1);
- else
- return DCG_emit_LEA(
- ptr,
- op&1 ? reg2 : reg1,
- op&2 ? reg2 : reg1,
- (op>>2) & 3,
- op&16 ? reg2 : reg1);
- } else if (op < CODE_SHL) {
- // special cases:
- // mov - scale=1
-
- if (!((op>>2)&3))
- return DCG_emit_MOV(ptr, op&1 ? reg2 : reg1, op&2 ? reg2 : reg1);
- else
- return DCG_emit_LEA(
- ptr,
- op&1 ? reg2 : reg1,
- op&2 ? reg2 : reg1,
- (op>>2) & 3);
- } else if (op < CODE_SUB) {
- // special cases:
- // add - shift=1
-
- if (((op-CODE_SHL)>>1)==1)
- return DCG_emit_ADD(ptr, op&1?reg2:reg1, op&1?reg2:reg1);
- else
- return DCG_emit_SHL(ptr, op&1?reg2:reg1, (op - CODE_SHL)>>1);
- } else {
- return DCG_emit_SUB(ptr, op&1?reg2:reg1, op&2?reg2:reg1);
- }
- }
-
- extern "C" char *asm_dynamic_convolute_codecopy(char *, int);
- extern "C" const char *const asm_const_multiply_tab[2049];
-
- int filter_convolute_start(FilterActivation *fa, const FilterFunctions *ff) {
- ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
- char *pptr,c;
- const char *pcode;
- int x, y;
- long m;
-
- ///////////////
-
- if (!g_dubOpts.perf.dynamicEnable) return 0;
-
- if (!(cfd->dyna_func = allocmem(4096))) return 1;
-
- pptr = (char *)cfd->dyna_func;
-
- _RPT0(0,"Generating code.\n");
-
- pptr = asm_dynamic_convolute_codecopy(pptr, 0);
-
- for(y=0; y<3; y++)
- for(x=0; x<3; x++) {
- m = cfd->m[(2-y)*3+x];
- if (!m) continue;
-
- _RPT3(0,"Matrix (%d,%d): coefficient %ld\n", x, y, m);
-
- // MOV eax,[esi+disp32]
- // SHR eax,(0/8/16)
- // AND eax,000000ffh
- // (generate multiplication series)
-
- // red=EBP, green=EDI, blue=EDX
-
- // If the coefficient is 2, 4, or 8, generate a compact LEA sequence
-
- if (m==2 || m==4 || m==8) {
- int scale = m>>2;
-
- // v MOV eax,[esi+disp32]
- // u MOV ebx,eax
- // v AND eax,000000ffh eax: ready
- // u MOV ecx,ebx
- // v AND ebx,0000ff00h
- // u SHR ebx,8 ebx: ready
- // v AND ecx,00ff0000h
- // u SHR ecx,16
- // v LEA edx,[edx+eax*mult]
- // u LEA edi,[edi+ebx*mult]
- // v LEA ebp,[ebp+ecx*mult] ;AGI (arrgh!!!)
-
- pptr = DCG_emit_MOV_from_indexed(pptr, REG_EAX, REG_ESI, fa->src.pitch*y + 4*x - 4);
- pptr = DCG_emit_MOV(pptr, REG_EBX, REG_EAX);
- pptr = DCG_emit_AND_immediate(pptr, REG_EAX, 0x000000ff);
- pptr = DCG_emit_MOV(pptr, REG_ECX, REG_EBX);
- pptr = DCG_emit_AND_immediate(pptr, REG_EBX, 0x0000ff00);
- pptr = DCG_emit_SHR(pptr, REG_EBX, 8);
- pptr = DCG_emit_AND_immediate(pptr, REG_ECX, 0x00ff0000);
- pptr = DCG_emit_SHR(pptr, REG_ECX, 16);
- pptr = DCG_emit_LEA(pptr, REG_EDX, REG_EAX, scale, REG_EDX);
- pptr = DCG_emit_LEA(pptr, REG_EDI, REG_EBX, scale, REG_EDI);
- pptr = DCG_emit_LEA(pptr, REG_EBP, REG_ECX, scale, REG_EBP);
-
- // If the coefficient is <=256, then generate red and blue simultaneously
-
- } else if (abs(m)<=256) {
-
- pptr = DCG_emit_MOV_from_indexed(pptr, REG_EAX, REG_ESI, fa->src.pitch*y + 4*x - 4);
- pptr = DCG_emit_AND_immediate(pptr, REG_EAX, 0x00ff00ff);
-
- pcode = asm_const_multiply_tab[abs(m)];
- while((c=*pcode++) != (char)0xff) {
- pptr = DCG_emit_mult_op(pptr, REG_EAX, REG_EBX, c);
- }
-
- pptr = DCG_emit_MOV(pptr, REG_EBX, REG_EAX);
-
- pptr = DCG_emit_SHR(pptr, REG_EAX, 16);
- pptr = DCG_emit_AND_immediate(pptr, REG_EBX, 0x0000ffff);
-
- if (m<0) pptr = DCG_emit_SUB(pptr, REG_EBP, REG_EAX);
- else pptr = DCG_emit_ADD(pptr, REG_EBP, REG_EAX);
-
- if (m<0) pptr = DCG_emit_SUB(pptr, REG_EDX, REG_EBX);
- else pptr = DCG_emit_ADD(pptr, REG_EDX, REG_EBX);
-
- } else {
-
- // red
-
- pptr = DCG_emit_MOV_from_indexed(pptr, REG_EAX, REG_ESI, fa->src.pitch*y + 4*x - 4);
- pptr = DCG_emit_SHR(pptr, REG_EAX, 16);
- pptr = DCG_emit_AND_immediate(pptr, REG_EAX, 0x000000ff);
-
- pcode = asm_const_multiply_tab[abs(m)];
- while((c=*pcode++) != (char)0xff) {
- pptr = DCG_emit_mult_op(pptr, REG_EAX, REG_EBX, c);
- }
-
- if (m<0) pptr = DCG_emit_SUB(pptr, REG_EBP, REG_EAX);
- else pptr = DCG_emit_ADD(pptr, REG_EBP, REG_EAX);
-
- // blue
-
- pptr = DCG_emit_MOV_from_indexed(pptr, REG_EAX, REG_ESI, fa->src.pitch*y + 4*x - 4);
- pptr = DCG_emit_AND_immediate(pptr, REG_EAX, 0x000000ff);
-
- pcode = asm_const_multiply_tab[abs(m)];
- while((c=*pcode++) != (char)0xff)
- pptr = DCG_emit_mult_op(pptr, REG_EAX, REG_EBX, c);
-
- if (m<0) pptr = DCG_emit_SUB(pptr, REG_EDX, REG_EAX);
- else pptr = DCG_emit_ADD(pptr, REG_EDX, REG_EAX);
- }
-
- // green
-
- pptr = DCG_emit_MOV_from_indexed(pptr, REG_EAX, REG_ESI, fa->src.pitch*y + 4*x - 4);
- pptr = DCG_emit_AND_immediate(pptr, REG_EAX, 0x0000ff00);
-
- pcode = asm_const_multiply_tab[abs(m)];
- while((c=*pcode++) != (char)0xff)
- pptr = DCG_emit_mult_op(pptr, REG_EAX, REG_EBX, c);
-
- if (m<0) pptr = DCG_emit_SUB(pptr, REG_EDI, REG_EAX);
- else pptr = DCG_emit_ADD(pptr, REG_EDI, REG_EAX);
-
-
- _RPT3(0,"Finished (%d,%d) - %ld bytes of code so far\n", x, y, pptr - (char *)cfd->dyna_func);
- }
-
- if (cfd->bias)
- pptr = asm_dynamic_convolute_codecopy(pptr, 1);
-
- pptr = asm_dynamic_convolute_codecopy(pptr, 2);
-
- pptr[0] = 0x0f;
- pptr[1] = (char)0x85;
- *(long *)(pptr+2) = (char *)cfd->dyna_func - (pptr+6);
- pptr[6] = (char)0xc3; // RET
-
- cfd->dyna_size = (pptr+6) - (char *)cfd->dyna_func;
-
- VirtualProtect(cfd->dyna_func, cfd->dyna_size, PAGE_EXECUTE_READWRITE, &cfd->dyna_old_protect);
-
- //////
-
- if (g_dubOpts.perf.dynamicShowDisassembly) {
- CodeDisassemblyWindow cdw(cfd->dyna_func, cfd->dyna_size, cfd->dyna_func, cfd->dyna_func);
-
- cdw.post(NULL);
- }
-
- return 0;
- }
-
- ///////////////////////////////////
-
- int filter_convolute_end(FilterActivation *fa, const FilterFunctions *ff) {
- ConvoluteFilterData *cfd = (ConvoluteFilterData *)fa->filter_data;
-
- if (cfd->dyna_func) {
- VirtualProtect(cfd->dyna_func, cfd->dyna_size, cfd->dyna_old_protect, &cfd->dyna_old_protect);
- freemem(cfd->dyna_func);
- cfd->dyna_func = NULL;
- }
-
- return 0;
- }
-
- FilterDefinition filterDef_convolute={
- 0,0,NULL,
- "general convolution",
- "Applies a general 3x3 convolution matrix to a pixel that depends on the pixel's value and the eight neighboring pixels around it.\n\n"
- "[Assembly optimized] [Dynamic compilation]",
- NULL,NULL,
- sizeof(ConvoluteFilterData),
- convolute_init,
- NULL,
- filter_convolute_run,
- filter_convolute_param,
- convolute_config,
- NULL,
- filter_convolute_start,
- filter_convolute_end,
- &convolute_obj,
- convolute_script_line,
- };